/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package se.kth.lwr.jeat.core;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import javax.measure.quantity.Dimensionless;
import javax.measure.unit.BaseUnit;
import javax.measure.unit.NonSI;
import javax.measure.unit.SI;
import javax.measure.unit.Unit;
import org.jscience.physics.amount.Amount;
import se.kth.lwr.jeat.samples.onsitetreatment.Units;

/**
 * This is an Impact model for determination of Global Warming Potential (CO2eq).
 * The model supports a 20, 100 and 500 years time horizon. Selection of time
 * horizon is done at object instantiation by three different factory methods:
 * <p>
 * <code>
 * get20yearsHorizonModel(), get100yearsHorizonModel(), get500yearsHorizonModel()</code>
 * </p>
 * The most frequently used GWP model - 100 years - have implemented support for
 * inclusion of FOSSIL and ELECTRICAL energy in the model.
 * 
 * 
 *
 * @author david
 */
public class GlobalWarmingModel extends ImpactModel {
    
    public static final Unit<Dimensionless> CO2Equivalents=new BaseUnit<>("CO2eq");

    private static Amount FossilFactor;

    //Determines what timehorizon this Global Warming Model use
    public static enum TIMEHORIZON {

        FIVE_HUNDRED_YEARS("500"),
        HUNDRED_YEARS("100"),
        TWENTY_YEARS("20");
        private String horizon;

        private TIMEHORIZON(String horizon) {
            this.horizon = horizon;
        }

        public String toString() {
            return horizon;
        }
    }
    //field for storage of GWP factors for air emissions
    private Map<EmissionCategory, Amount> emissionFactors;
    //field for storage of GWP factors for energy use
    private Map<EnergyCategory, Amount> energyFacors;
    //field for Timehorizon
    private TIMEHORIZON TH;

    /**
     * Creates an Impact model for Global Warming Potential. At creation, select
     * among three different time horizons.
     *
     * @param horizon the choise of TIMEHORIZON
     */
    private GlobalWarmingModel(TIMEHORIZON horizon, String additionalDescriptionText) {
        super("GWP (" + horizon + " years time horizon)",
                "Global warming potential with a " + horizon + " years time horizon."
                + " Data based on IPCC AR4 p212, 2007. " + additionalDescriptionText);
        this.TH = horizon;
        emissionFactors = new HashMap<>();
        energyFacors = new HashMap<>();
        //setup Map with factors;
        switch (TH) {
            case FIVE_HUNDRED_YEARS:
                emissionFactors.put(EmissionCategory.CO2, Amount.valueOf(1, Units.CO2Eqvivalent));
                emissionFactors.put(EmissionCategory.CH4, Amount.valueOf(7.6, Units.CO2Eqvivalent));
                emissionFactors.put(EmissionCategory.N2O, Amount.valueOf(153, Units.CO2Eqvivalent));
                emissionFactors.put(EmissionCategory.HFC23, Amount.valueOf(12200, Units.CO2Eqvivalent));
                emissionFactors.put(EmissionCategory.HFC134a, Amount.valueOf(435, Units.CO2Eqvivalent));
                emissionFactors.put(EmissionCategory.SF6, Amount.valueOf(32600, Units.CO2Eqvivalent));
                break;
            case HUNDRED_YEARS:
                emissionFactors.put(EmissionCategory.CO2, Amount.valueOf(1, Units.CO2Eqvivalent));
                emissionFactors.put(EmissionCategory.CH4, Amount.valueOf(25, Units.CO2Eqvivalent));
                emissionFactors.put(EmissionCategory.N2O, Amount.valueOf(298, Units.CO2Eqvivalent));
                emissionFactors.put(EmissionCategory.HFC23, Amount.valueOf(14800, Units.CO2Eqvivalent));
                emissionFactors.put(EmissionCategory.HFC134a, Amount.valueOf(1430, Units.CO2Eqvivalent));
                emissionFactors.put(EmissionCategory.SF6, Amount.valueOf(22800, Units.CO2Eqvivalent));
                energyFacors.put(EnergyCategory.ELECTRICAL, Amount.valueOf(97.3, SI.GRAM.times(Units.CO2Eqvivalent).divide(SI.KILO(SI.WATT).times(NonSI.HOUR))));
                Amount a = Amount.valueOf(97.3, SI.GRAM.times(Units.CO2Eqvivalent).divide(SI.KILO(SI.WATT).times(NonSI.HOUR)));
                //System.out.println(a.to(SI.KILOGRAM.times(Units.CO2Eqvivalent).divide(SI.MEGA(SI.JOULE))));
                //calculate aggregated factor for fossil fuels
                FossilFactor = getImpact(heavy_truck_emissions.readValue());
                //System.out.println(FossilFactor.to(SI.KILOGRAM.times(Units.CO2Eqvivalent).divide(SI.MEGA(SI.JOULE))));
               
                energyFacors.put(EnergyCategory.FOSSIL, FossilFactor);

                break;
            case TWENTY_YEARS:
                emissionFactors.put(EmissionCategory.CO2, Amount.ONE);
                emissionFactors.put(EmissionCategory.CH4, Amount.valueOf(72, Unit.ONE));
                emissionFactors.put(EmissionCategory.N2O, Amount.valueOf(289, Unit.ONE));
                emissionFactors.put(EmissionCategory.HFC23, Amount.valueOf(12000, Unit.ONE));
                emissionFactors.put(EmissionCategory.HFC134a, Amount.valueOf(3830, Unit.ONE));
                emissionFactors.put(EmissionCategory.SF6, Amount.valueOf(16300, Unit.ONE));
                break;

        }



    }

    /**
     * Creates an Impact model for Global Warming Potential with a 20 years time
     * horizon.
     *
     * @return A GlobalWarmingModel with 20 years time horizon
     */
    public static GlobalWarmingModel get20yearsHorizonModel() {
        return new GlobalWarmingModel(TIMEHORIZON.TWENTY_YEARS, "");
    }

    /**
     * Creates an Impact model for Global Warming Potential with a 100 years
     * time horizon.
     *
     * @return A GlobalWarmingModel with 100 years time horizon
     */
    public static GlobalWarmingModel get100yearsHorizonModel() {
        return new GlobalWarmingModel(TIMEHORIZON.HUNDRED_YEARS, "Contribution from"
                + "the energy pools \"ELECTRICAL\" and \"FOSSIL\" are included "
                + "trough eqvivalency factors derived from a Nordic Electricy mix and "
                + "diesel (5%RME) use in a heavy truck without trailer respectively. "
                + "Emission data from (Miljöfaktabok 2011, Värmeforsk)");
    }

    /**
     * Creates an Impact model for Global Warming Potential with a 500 years
     * time horizon.
     *
     * @return A GlobalWarmingModel with 500 years time horizon
     */
    public static GlobalWarmingModel get500yearsHorizonModel() {
        return new GlobalWarmingModel(TIMEHORIZON.FIVE_HUNDRED_YEARS, "");
    }

    @Override
    public Amount<?> getImpact(Inventoriable inventoriable) {
        //get the inventory
        Inventory inventory = inventoriable.getInventory();

        //Set of energy keys
        Set<EnergyCategory> energyKeys = energyFacors.keySet();

        //prepare empty returnvalue
        Amount retval = null;

        //add contribution from energy pool
        for (EnergyCategory powerCategory : energyKeys) {
            if (inventory.getEnergyUse(powerCategory) != null) {
                //calculate GWP contribution
                Amount additive = energyFacors.get(powerCategory).times(inventory.getEnergyUse(powerCategory));
                //first Unit sets the standard for the resulting Amount
                if (retval == null) {
                    retval = additive;
                } else {
                    //continue by addition
                    retval = retval.plus(additive);
                }
            }
        }

        //Set of emission keys
        Set<EmissionCategory> emissionKeys = emissionFactors.keySet();

        //add contribution from air emission pool
        for (EmissionCategory emissionCategory : emissionKeys) {
            if (inventory.getEmissionToAir(emissionCategory) != null) {
                //calculate GWP contribution
                Amount additive = emissionFactors.get(emissionCategory).times(inventory.getEmissionToAir(emissionCategory));
                //first Unit sets the standard for the resulting Amount
                if (retval == null) {
                    retval = additive;
                } else {
                    //continue by addition
                    retval = retval.plus(additive);

                }


            }
        }
        //return result
        return retval;
    }
    
    /**
     * 
     * @return the unit specifying the value of the impact (CO2-equivalents)
     */

    @Override
    public Unit getUnit() {
        return CO2Equivalents;
    }
    /**
     * Air emissions for diesel (5% RME) use in heavy truck without trailer.
     * (Miljöfaktabok för bränslen 2012)
     *
     */
    public static final InventoryDataSource heavy_truck_emissions = new InventoryDataSource("heavy_truck_emissions",
            "Air emissions for diesel (5% RME) use in heavy truck without trailer. (Miljöfaktabok för bränslen 2012)",
            new Inventoriable() {

                @Override
                public Inventory getInventory() {
                    Inventory retval = Inventory.emptyInventory();
                    retval.addEmissionToAir(EmissionCategory.CH4, Amount.valueOf(0.830, SI.MILLI(Unit.valueOf("g/MJ"))));
                    retval.addEmissionToAir(EmissionCategory.CO2, Amount.valueOf(69.6, Unit.valueOf("g/MJ")));
                    retval.addEmissionToAir(EmissionCategory.CO, Amount.valueOf(0.15, Unit.valueOf("g/MJ")));
                    retval.addEmissionToAir(EmissionCategory.N2O, Amount.valueOf(1, SI.MILLI(Unit.valueOf("g/MJ"))));
                    retval.addEmissionToAir(EmissionCategory.NOx, Amount.valueOf(0.68, Unit.valueOf("g/MJ")));
                    return retval;
                }
            });
}
